home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 8 / The Arsenal Files Collection #8 (Arsenal Computer) (1996).ISO / g_quake / ffield.zip / COMBAT.QC < prev    next >
Text File  |  1996-10-28  |  7KB  |  300 lines

  1. void() T_MissileTouch;
  2. void() info_player_start;
  3. void(entity targ, entity attacker) ClientObituary;
  4.  
  5. void() monster_death_use;
  6.  
  7. //============================================================================
  8.  
  9. /*
  10. ============
  11. CanDamage
  12.  
  13. Returns true if the inflictor can directly damage the target.  Used for
  14. explosions and melee attacks.
  15. ============
  16. */
  17. float(entity targ, entity inflictor) CanDamage =
  18. {
  19. // bmodels need special checking because their origin is 0,0,0
  20.     if (targ.movetype == MOVETYPE_PUSH)
  21.     {
  22.         traceline(inflictor.origin, 0.5 * (targ.absmin + targ.absmax), TRUE, self);
  23.         if (trace_fraction == 1)
  24.             return TRUE;
  25.         if (trace_ent == targ)
  26.             return TRUE;
  27.         return FALSE;
  28.     }
  29.     
  30.     traceline(inflictor.origin, targ.origin, TRUE, self);
  31.     if (trace_fraction == 1)
  32.         return TRUE;
  33.     traceline(inflictor.origin, targ.origin + '15 15 0', TRUE, self);
  34.     if (trace_fraction == 1)
  35.         return TRUE;
  36.     traceline(inflictor.origin, targ.origin + '-15 -15 0', TRUE, self);
  37.     if (trace_fraction == 1)
  38.         return TRUE;
  39.     traceline(inflictor.origin, targ.origin + '-15 15 0', TRUE, self);
  40.     if (trace_fraction == 1)
  41.         return TRUE;
  42.     traceline(inflictor.origin, targ.origin + '15 -15 0', TRUE, self);
  43.     if (trace_fraction == 1)
  44.         return TRUE;
  45.  
  46.     return FALSE;
  47. };
  48.  
  49. /*
  50. ============
  51. Killed
  52. ============
  53. */
  54. void(entity targ, entity attacker) Killed =
  55. {
  56.     local entity oself;
  57.  
  58.     oself = self;
  59.     self = targ;
  60.     
  61.     if (self.health < -99)
  62.         self.health = -99;        // don't let sbar look bad if a player
  63.  
  64.     if (self.movetype == MOVETYPE_PUSH || self.movetype == MOVETYPE_NONE)
  65.     {    // doors, triggers, etc
  66.         self.th_die ();
  67.         self = oself;
  68.         return;
  69.     }
  70.  
  71.     self.enemy = attacker;
  72.  
  73. // bump the monster counter
  74.     if (self.flags & FL_MONSTER)
  75.     {
  76.         killed_monsters = killed_monsters + 1;
  77.         WriteByte (MSG_ALL, SVC_KILLEDMONSTER);
  78.     }
  79.  
  80.     ClientObituary(self, attacker);
  81.     
  82.     self.takedamage = DAMAGE_NO;
  83.     self.touch = SUB_Null;
  84.  
  85.     monster_death_use();
  86.     self.th_die ();
  87.     
  88.     self = oself;
  89. };
  90.  
  91.  
  92. /*
  93. ============
  94. T_Damage
  95.  
  96. The damage is coming from inflictor, but get mad at attacker
  97. This should be the only function that ever reduces health.
  98. ============
  99. */
  100. void(entity targ, entity inflictor, entity attacker, float damage) T_Damage=
  101. {
  102.     local    vector    dir;
  103.     local    entity    oldself;
  104.     local    float    save;
  105.     local    float    take;
  106.         local   float   UnionTempDamage;
  107.  
  108.     if (!targ.takedamage)
  109.         return;
  110.  
  111. // used by buttons and triggers to set activator for target firing
  112.     damage_attacker = attacker;
  113.  
  114. // check for quad damage powerup on the attacker
  115.     if (attacker.super_damage_finished > time)
  116.         damage = damage * 4;
  117.  
  118. // <JRS>
  119. // Check to see if the force field is on.
  120.         if (targ.Union_ForceField_On)
  121.         {
  122.                 UnionTempDamage = damage;
  123.                 damage = UnionFFTakeDamage(targ, damage);
  124. //                particle(targ.origin, '0 0 100', 111, UnionTempDamage - damage);
  125.                 stuffcmd (targ, "bf\n");
  126.                 sound(targ,CHAN_AUTO,"sound/FF/FF_Hit.wav",1,ATTN_NORM);
  127.         }
  128.         if (damage == 0)
  129.                 return;
  130.  
  131. // </JRS>
  132.  
  133. // save damage based on the target's armor level
  134.  
  135.     save = ceil(targ.armortype*damage);
  136.     if (save >= targ.armorvalue)
  137.     {
  138.         save = targ.armorvalue;
  139.         targ.armortype = 0;    // lost all armor
  140.         targ.items = targ.items - (targ.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3));
  141.     }
  142.     
  143.     targ.armorvalue = targ.armorvalue - save;
  144.     take = ceil(damage-save);
  145.  
  146. // add to the damage total for clients, which will be sent as a single
  147. // message at the end of the frame
  148. // FIXME: remove after combining shotgun blasts?
  149.     if (targ.flags & FL_CLIENT)
  150.     {
  151.         targ.dmg_take = targ.dmg_take + take;
  152.         targ.dmg_save = targ.dmg_save + save;
  153.         targ.dmg_inflictor = inflictor;
  154.     }
  155.  
  156. // figure momentum add
  157.     if ( (inflictor != world) && (targ.movetype == MOVETYPE_WALK) )
  158.     {
  159.         dir = targ.origin - (inflictor.absmin + inflictor.absmax) * 0.5;
  160.         dir = normalize(dir);
  161.         targ.velocity = targ.velocity + dir*damage*8;
  162.     }
  163.  
  164. // check for godmode or invincibility
  165.     if (targ.flags & FL_GODMODE)
  166.         return;
  167.     if (targ.invincible_finished >= time)
  168.     {
  169.         if (self.invincible_sound < time)
  170.         {
  171.             sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
  172.             self.invincible_sound = time + 2;
  173.         }
  174.         return;
  175.     }
  176.  
  177. // team play damage avoidance
  178.     if ( (teamplay == 1) && (targ.team > 0)&&(targ.team == attacker.team) )
  179.         return;
  180.         
  181. // do the damage
  182.     targ.health = targ.health - take;
  183.             
  184.     if (targ.health <= 0)
  185.     {
  186.         Killed (targ, attacker);
  187.         return;
  188.     }
  189.  
  190. // react to the damage
  191.     oldself = self;
  192.     self = targ;
  193.  
  194.     if ( (self.flags & FL_MONSTER) && attacker != world)
  195.     {
  196.     // get mad unless of the same class (except for soldiers)
  197.         if (self != attacker && attacker != self.enemy)
  198.         {
  199.             if ( (self.classname != attacker.classname) 
  200.             || (self.classname == "monster_army" ) )
  201.             {
  202.                 if (self.enemy.classname == "player")
  203.                     self.oldenemy = self.enemy;
  204.                 self.enemy = attacker;
  205.                 FoundTarget ();
  206.             }
  207.         }
  208.     }
  209.  
  210.     if (self.th_pain)
  211.     {
  212.         self.th_pain (attacker, take);
  213.     // nightmare mode monsters don't go into pain frames often
  214.         if (skill == 3)
  215.             self.pain_finished = time + 5;        
  216.     }
  217.  
  218.     self = oldself;
  219. };
  220.  
  221. /*
  222. ============
  223. T_RadiusDamage
  224. ============
  225. */
  226. void(entity inflictor, entity attacker, float damage, entity ignore) T_RadiusDamage =
  227. {
  228.     local    float     points;
  229.     local    entity    head;
  230.     local    vector    org;
  231.  
  232.     head = findradius(inflictor.origin, damage+40);
  233.     
  234.     while (head)
  235.     {
  236.         if (head != ignore)
  237.         {
  238.             if (head.takedamage)
  239.             {
  240.                 org = head.origin + (head.mins + head.maxs)*0.5;
  241.                 points = 0.5*vlen (inflictor.origin - org);
  242.                 if (points < 0)
  243.                     points = 0;
  244.                 points = damage - points;
  245.                 if (head == attacker)
  246.                     points = points * 0.5;
  247.                 if (points > 0)
  248.                 {
  249.                     if (CanDamage (head, inflictor))
  250.                     {    // shambler takes half damage from all explosions
  251.                         if (head.classname == "monster_shambler")                        
  252.                             T_Damage (head, inflictor, attacker, points*0.5);
  253.                         else
  254.                             T_Damage (head, inflictor, attacker, points);
  255.                     }
  256.                 }
  257.             }
  258.         }
  259.         head = head.chain;
  260.     }
  261. };
  262.  
  263. /*
  264. ============
  265. T_BeamDamage
  266. ============
  267. */
  268. void(entity attacker, float damage) T_BeamDamage =
  269. {
  270.     local    float     points;
  271.     local    entity    head;
  272.     
  273.     head = findradius(attacker.origin, damage+40);
  274.     
  275.     while (head)
  276.     {
  277.         if (head.takedamage)
  278.         {
  279.             points = 0.5*vlen (attacker.origin - head.origin);
  280.             if (points < 0)
  281.                 points = 0;
  282.             points = damage - points;
  283.             if (head == attacker)
  284.                 points = points * 0.5;
  285.             if (points > 0)
  286.             {
  287.                 if (CanDamage (head, attacker))
  288.                 {
  289.                     if (head.classname == "monster_shambler")                        
  290.                         T_Damage (head, attacker, attacker, points*0.5);
  291.                     else
  292.                         T_Damage (head, attacker, attacker, points);
  293.                 }
  294.             }
  295.         }
  296.         head = head.chain;
  297.     }
  298. };
  299.  
  300.